﻿using OpenTK.Graphics.OpenGL4;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Mathematics;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Core.Rendering.Resources;
using Core.Log;
using Core.Maths;
using PrimitiveType = OpenTK.Graphics.OpenGL4.PrimitiveType;
using Core.Rendering;
using Core.Rendering.Buffer;
using Core.ECS.Components;
using Core.Tools;
using DefaultEcs;
using Core.ECS;

namespace Core
{
    public class Window : GameWindow
    {
        private float width;
        private float height;
        private Model _myModel;
        private Shader _shader;
        private Texture2D _texture;
        private CCamera _camera;
        private UniformBufferObject _ubo;
        CTransform modelTransform;
        Scene scene;
        public Window(int width, int height, string title) : base(GameWindowSettings.Default, new NativeWindowSettings() { ClientSize = (width, height), Title = title }) { }
        protected override void OnLoad()
        {
            //_camera = new CCamera(Guid.NewGuid());
            //Actor cameraActor = new Actor();
            //_camera.Actor = cameraActor;
            //cameraActor.Transform.LocalPosition = Vector3.UnitZ * -20;
            //_ubo = new UniformBufferObject(1024,0);
            //Core.Rendering.Resources.Material material = new Core.Rendering.Resources.Material("./resources/objects/backpack/diffuse.jpg", "./Test.glsl");
            //SerializeHelper.Serialize(material, "./material.xml");
            //SerializeHelper.Deserialize("./material.xml",out Core.Rendering.Resources.Material material);
            //scene = new Scene();
            //actor = new Actor();
            //actor.BehaviorsName.Add("Core.ECS.Components.TestBehavior");
            //SerializeHelper.Serialize(actor, "./actor.xml");
            //SerializeHelper.Deserialize("actor.xml",out actor);
            //actor.window = this;
            //actor2 = new Actor();
            //actor2.Transform.LocalPosition = Vector3.UnitX * -5 + Vector3.UnitZ * 5;
            //scene.Actors.Add(actor);
            //scene.Actors.Add(actor2);
            SerializeHelper.Deserialize("scene.scene", out scene);
            //scene.ActorsList[1].SetName("Actor1");
            //scene.ActorsList[1].Transform.Parent = scene.ActorsList[0].Transform;
            //SerializeHelper.Serialize(scene, "scene.scene");
            //scene.MainCamera.Actor.BehaviorsName.Add("Core.ECS.Components.TestCameraBehavior");
            //SerializeHelper.Serialize(scene,"scene.xml");
            //scene.MainCamera = _camera;
            //cameraActor.ClearRender();
            //SerializeHelper.Serialize(scene, "scene.xml");
            Scene.Window = this;
            scene.UniformBufferObject = new();
            foreach (var actor in scene.Actors.Values)
            {
                actor.RenderStart();
                actor.Transform.UpdateParent();
            }
            scene.MainCamera.Actor.BehaviorStart();
            foreach (var actor in scene.Actors.Values)
            {
                actor.BehaviorStart();
            }
            foreach (var behavior in scene.MainCamera.Actor.Behaviors)
            {
                behavior.Start();
            }
            foreach (var actor in scene.Actors.Values)
            {
                //if (!scene.ActorsByName.ContainsKey(actor.Name))
                //{
                //    scene.ActorsByName.Add(actor.Name, actor);
                //}
                foreach (var behavior in actor.Behaviors)
                {
                    behavior.Start();
                }
            }
            //SerializeHelper.Serialize(scene, "scene.scene");
            //_shader = Shader.Create("./Test.glsl");
            //UniformBufferObject.BindingPointToShader(_shader!,"EngineUbo", 0);
            //_myModel = Model.Create("./resources/objects/backpack/backpack.obj");
            //_texture = Texture2D.Create("./resources/objects/backpack/diffuse.jpg");
            //_texture = Texture2D.Create(Color4.Red);
        }
        //private Matrix4 _model;//世界空间
        //private Matrix4 _view;//观察空间
        //private Matrix4 _perspective;//透视矩阵
        //private float _totalTime = 0;
        protected override void OnRenderFrame(FrameEventArgs args)
        {
            //清除缓冲区加深度测试
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
            GL.Enable(EnableCap.DepthTest);
            //处理相机
            GL.ClearColor(scene.MainCamera!.ClearColor);
            foreach (var behavior in scene.MainCamera.Actor.Behaviors)
            {
                behavior.Update();
            }
            scene.MainCamera.UpdateMatrices(scene.MainCamera.Actor.Transform, width, height);
            scene.UniformBufferObject?.SetData(scene.MainCamera.ViewMatrix, 64);
            scene.UniformBufferObject?.SetData(scene.MainCamera.PerspectiveMatrix, 128);
            //逐个处理除相机外Actor
            foreach (Actor actor in scene.Actors.Values)
            {
                if(actor.Active == false) continue;
                //处理碰撞
                //if(actor.GetComponent<CBoxCollider>() != null)
                //{
                //    foreach(Actor actor1 in scene.Actors.Values)
                //    {
                //        if(actor != actor1)
                //        {
                //            CBoxCollider collider1 = actor1.GetComponent<CBoxCollider>();
                //            CBoxCollider collider2 = actor.GetComponent<CBoxCollider>();
                //            if (collider1!= null && collider2 != null && CBoxCollider.CheckCollider(collider1, collider2))
                //            {
                //                ExLog.InfoLogCore("1");
                //            }
                //        }
                //    }
                //}
                //处理Update和渲染
                if (actor.Active)
                {
                    foreach (var behavior in actor.Behaviors)
                    {
                        behavior.Update();
                    }
                    scene.UniformBufferObject!.SetData(actor.Transform.WorldMatrix, 0);
                    actor.RendererBind();
                }
            }
            //_model = Matrix4.Identity * Matrix4.CreateRotationY(MathHelper.DegreesToRadians(30) * _totalTime);
            //cmodel.Material?.Bind();
            //foreach (var mesh in cmodel.Model.Meshes)
            //{
            //    mesh.Bind();
            //    if (mesh.IndexCount > 3)
            //    {
            //        GL.DrawElements(PrimitiveType.Triangles, mesh.IndexCount, DrawElementsType.UnsignedInt, 0);
            //    }
            //    else
            //    {
            //        GL.DrawArrays(PrimitiveType.Triangles, 0, mesh.VertexCount);
            //    }
            //}
            SwapBuffers();
        }
        protected override void OnUpdateFrame(FrameEventArgs args)
        {
            foreach (var behavior in scene.MainCamera.Actor.Behaviors)
            {
                behavior.FixedUpdate();
            }
            foreach (var actor in scene.Actors.Values)
            {
                foreach (var behavior in actor.Behaviors)
                {
                    behavior.FixedUpdate();
                }
            }
            if (KeyboardState.IsKeyDown(Keys.Escape))
            {
                Close();
            }
        }
        protected override void OnResize(ResizeEventArgs e)
        {
            GL.Viewport(0, 0, e.Width, e.Height);
            width = e.Width;
            height = e.Height;
        }
    }
}
